import { t } from 'i18next'
import { Editor, EditorEvents } from '@tiptap/core'
import { Slice } from '@tiptap/pm/model'
import { AbstractDropdownMenuButton } from '../AbstractDropdownMenuButton'
import { Icons } from './Icons'
import { InnerEditor } from '../..'


export function removeDivByClassName(htmlString: string, className: string): string {
  // 创建一个新的DOM解析器
  const parser = new DOMParser();
  const doc = parser.parseFromString(htmlString, 'text/html');

  // 获取所有具有指定类名的div元素
  const divsToRemove = doc.querySelectorAll(`div.${className}`);

  // 遍历并移除这些元素
  divsToRemove.forEach(div => div.remove());

  // 将修改后的DOM转换回字符串
  return doc.body.innerHTML;
}

export interface AiAppActionMenu {
  icon: string
  name: string
  prompt?: string
  text?: 'selected' | 'focusBefore'
  model?: string
  action?: () => void
}

export abstract class AbstractAppMessageActionMenu extends AbstractDropdownMenuButton<AiAppActionMenu> {
  constructor() {
    super()
    this.dropDivHeight = 'auto'
    this.dropDivWith = 'fit-content'
    this.width = '36px'
    this.menuTextWidth = '20px'
  }

  renderTemplate() {
    this.template = `<div style="width: ${this.width};">
            <div id="tippy" style="display: flex">
                📝<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="8 0 16 16"><path fill="none" d="M0 0h24v24H0z"></path><path d="M12 14L8 10H16L12 14Z"></path></svg>
            </div>
        </div>
        `
  }

  createMenuElement() {
    const div = document.createElement('div')
    div.style.height = this.dropDivHeight
    div.style.width = this.dropDivWith
    div.classList.add('aie-dropdown-container')

    for (let i = 0; i < this.menuData.length; i++) {
      const item = document.createElement('div')
      item.classList.add('aie-dropdown-item')
      item.innerHTML = `
                <div class="text" style="display: flex;padding: 5px">${this.onDropdownItemRender(i)}</div>
                `
      item.addEventListener('click', (evt) => {
        const menuItem = this.menuData[i] as any
        if (menuItem.onClick) {
          const result = menuItem.onClick(evt)
          if (result) this.tippyInstance!.hide()
        } else {
          this.onDropdownItemClick(i)
          this.tippyInstance!.hide()
        }
      })
      div.appendChild(item)
    }
    this.tippyEl = div
    return div
  }

  onTransaction(_: EditorEvents['transaction']) {
    //do nothing
  }

  onDropdownActive(_editor: Editor, _index: number): boolean {
    return false
  }

  onDropdownItemClick(index: number): void {
    const aiMenu = this.menuData[index]
    aiMenu.action?.call(this)
  }

  onDropdownItemRender(index: number): Element | string {
    return `<div style="width:18px;height: 18px;">${this.menuData[index].icon}</div><div style="margin-left: 10px">${this.menuData[index].name}</div>`
  }

  onMenuTextRender(index: number): Element | string {
    return this.menuData[index].icon
  }
}

export class AppMessageActionMenu extends AbstractAppMessageActionMenu {
  sourceDivElement!: HTMLElement
  sourceInputElement!: HTMLElement

  defaultAiActionMenus: AiAppActionMenu[] = [
    {
      icon: Icons.EditAction,
      name: `ai-edit`,
      action: () => {
        (this.sourceInputElement as HTMLTextAreaElement).value = this.sourceDivElement.innerText
        this.sourceInputElement.style.height = 'auto'
        this.sourceInputElement.style.height = this.sourceInputElement.scrollHeight + 'px'
      }
    },
    {
      icon: Icons.InsertAction,
      name: `ai-append`,
      action: () => {
        const {
          state: { selection, tr },
          view: { dispatch }
        } = this.editor!
        // const content = (this.editor as InnerEditor).parseHtml(removeDivByClassName(this.sourceDivElement.innerHTML, "aie-codeblock-tools"));
        const content =  (this.editor as InnerEditor).parseMarkdown(this.sourceDivElement.getAttribute("InnerContent")!);
        dispatch(tr.replace(selection.to, selection.to, new Slice(content, 0, 0)).scrollIntoView())
      }
    },
    {
      icon: Icons.ReplaceAction,
      name: `ai-replace`,
      action: () => {
        const {
          state: { tr },
          view: { dispatch }
        } = this.editor!
        // const content = (this.editor as InnerEditor).parseHtml(removeDivByClassName(this.sourceDivElement.innerHTML, "aie-codeblock-tools"));
        const content =  (this.editor as InnerEditor).parseMarkdown(this.sourceDivElement.getAttribute("InnerContent")!);
        dispatch(tr.replaceSelection(new Slice(content, 0, 0)).scrollIntoView())
      }
    }
  ]

  constructor() {
    super()
    this.menuData = this.defaultAiActionMenus.map((menu) => {
      return {
        ...menu,
        name: `${t(menu.name)}`
      }
    })
  }

  bindSourceElement(sourceDivElement: HTMLElement, sourceInputElement: HTMLElement) {
    this.sourceDivElement = sourceDivElement
    this.sourceInputElement = sourceInputElement
  }
}

export class AppResponseActionMenu extends AbstractAppMessageActionMenu {
  sourceDivElement!: HTMLElement

  defaultAiActionMenus: AiAppActionMenu[] = [
    {
      icon: Icons.InsertAction,
      name: `ai-append`,
      action: () => {
        const {
          state: { selection, tr },
          view: { dispatch }
        } = this.editor!
        // const content = (this.editor as InnerEditor).parseHtml(removeDivByClassName(this.sourceDivElement.innerHTML, "aie-codeblock-tools"));
        const content =  (this.editor as InnerEditor).parseMarkdown(this.sourceDivElement.getAttribute("InnerContent")!);
        dispatch(tr.replace(selection.to, selection.to, new Slice(content, 0, 0)).scrollIntoView())
      }
    },
    {
      icon: Icons.ReplaceAction,
      name: `ai-replace`,
      action: () => {
        const {
          state: { tr },
          view: { dispatch }
        } = this.editor!
        // const content = (this.editor as InnerEditor).parseHtml(removeDivByClassName(this.sourceDivElement.innerHTML, "aie-codeblock-tools"));
        const content =  (this.editor as InnerEditor).parseMarkdown(this.sourceDivElement.getAttribute("InnerContent")!);
        dispatch(tr.replaceSelection(new Slice(content, 0, 0)).scrollIntoView())
      }
    }
  ]

  constructor() {
    super()
    this.menuData = this.defaultAiActionMenus.map((menu) => {
      return {
        ...menu,
        name: `${t(menu.name)}`
      }
    })
  }

  bindSourceElement(sourceDivElement: HTMLElement) {
    this.sourceDivElement = sourceDivElement
  }
}

export class AppImageResponseActionMenu extends AbstractAppMessageActionMenu {
  sourceDivElement!: HTMLElement

  defaultAiActionMenus: AiAppActionMenu[] = [
    {
      icon: Icons.InsertAction,
      name: `ai-append`,
      action: () => {
        const {
          state: { selection, tr },
          view: { dispatch }
        } = this.editor!
        const content =  (this.editor as InnerEditor).parseMarkdown(this.sourceDivElement.innerHTML);
        dispatch(tr.replace(selection.to, selection.to, new Slice(content, 0, 0)).scrollIntoView())
      }
    },
    {
      icon: Icons.ReplaceAction,
      name: `ai-replace`,
      action: () => {
        const {
          state: { tr },
          view: { dispatch }
        } = this.editor!
        const content =  (this.editor as InnerEditor).parseMarkdown(this.sourceDivElement.innerHTML);
        dispatch(tr.replaceSelection(new Slice(content, 0, 0)).scrollIntoView())
      }
    }
  ]

  constructor() {
    super()
    this.menuData = this.defaultAiActionMenus.map((menu) => {
      return {
        ...menu,
        name: `${t(menu.name)}`
      }
    })
  }

  bindSourceElement(sourceDivElement: HTMLElement) {
    this.sourceDivElement = sourceDivElement
  }
}
